/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021.
 * Description: provide enable proc file of rtos improve perf user backtrace feature
 * Author: chenzechuan
 * Create: 2021-7-20
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/rtos_perf_user_backtrace.h>

#define INPUT_LEN 2
#define OUTPUT_LEN 3

unsigned int improve_perf_user_backtrace_enable = 1;
DEFINE_RWLOCK(improve_perf_user_backtrace_lock);

static ssize_t proc_enable_read(struct file *file, char __user *buf,
				size_t count, loff_t *ppos)
{
	char loc_buf[OUTPUT_LEN];

	snprintf(loc_buf, sizeof(loc_buf),
		 "%d\n", improve_perf_user_backtrace_enable);
	return simple_read_from_buffer(buf, count, ppos, loc_buf, strlen(loc_buf));
}

static ssize_t proc_enable_write(struct file *file, const char __user *buf,
				size_t count, loff_t *off)
{
	int val = 0;

	if (count == 0 || count > INPUT_LEN) {
		pr_err("input string error! please input \"0\" or \"1\"\n");
		return -EINVAL;
	}

	if (kstrtoint_from_user(buf, count, 0, &val)) {
		pr_err("input string error! non-numeric characters exist\n");
		return -EINVAL;
	}

	if (val < 0 || val > 1) {
		pr_err("input value error! please input \"0\" or \"1\"\n");
		return -EINVAL;
	}

	write_lock(&improve_perf_user_backtrace_lock);
	improve_perf_user_backtrace_enable = val;
	write_unlock(&improve_perf_user_backtrace_lock);

	return count;
}

static const struct proc_ops proc_enbale_fops = {
	.proc_read   = proc_enable_read,
	.proc_write  = proc_enable_write,
};

static int __init init_improve_perf_user_backtrace_proc(void)
{
	struct proc_dir_entry *pe = proc_create("perf_fp_backtrace_enable", 0640,
						NULL, &proc_enbale_fops);
	if (!pe)
		return -ENOMEM;

	return 0;
}

module_init(init_improve_perf_user_backtrace_proc);
